环境:
每台服务器安装CentOS 7.2 Minimal 版本,安装后使用yum update更新一下最新的系统内核和相关配置参数。
MariaDB galera集群建议最少3台服务器,2台无法保证数据完整性。
几台虚拟机ip设置如下:
节点名称 IP地址
cluster1 192.168.56.21
cluster2 192.168.56.22
cluster3 192.168.56.23
删除CentOS自带的老版本mariadb lib文件
查找安装的mariadb
sudo rpm -qa | grep mariadb
删除查找到的lib文件
sudo rpm -e --nodeps (这里是查找到的mariadb lib 文件)
安全设置
1) firewall
因为安装mariadb galera 需要打开 3306、4444、4567、4568四个端口,而且要降低安全审核级别。
使用以下命令设置防火墙开放这几个端口:
3306是MariaDB/mysql的服务端口,这个都不开那就不用跑MariaDB/MySQL服务了,需要开TCP端口;
4567是Galera做数据复制的通讯和数据传输端口,需要在防火墙放开TCP和UDP;
4568是Galera做增量数据传输使用的端口(Incremental State Transfer, IST),需要防火墙放开TCP;
4444是Galera做快照状态传输使用的端口(State Snapshot Transfer, SST),需要防火墙放开TCP。)
sudo firewall-cmd --permanent --zone=public --add-port={3306,4567,4568,4444}/tcp
sudo firewall-cmd --permanent --zone=public --add-port=4567/udp
sudo firewall-cmd --reload (重新加载防火墙使修改生效)
2) selinux
在CentOS的SELinux配置文件中降低SELinux的安全审核级别,让mysqld可以正常运行,否则SELinux会限制集群数据传输
(setenforce 0 命令只能设置运行时的安全级别,想要完全设置安全级别,需要在SELinux的配置文件中进行配置更改)
使用vi 打开/etc/selinux/config配置文件,设置SELINUX=permissive
sudo vi /etc/selinux/config
或者键入命令 semanage permissive -a mysqld_t
使用reboot命令重启服务器使SELinux安全级别更改生效
配置 yum源
1) 配置 mariadb 10.2 yum源
官网地址 https://downloads.mariadb.org/
选择最新稳定版本 MariaDB Galera Cluster 10.2 Series
(原有下载地址太慢,需要换成国内的镜像地址)
1 |
|
2) 配置 percona yum源
1 |
|
3) 配置 epel 源
1 |
|
4)配置 centos base 源
1 |
|
安装
1) 安装 mariadb
yum install -y MariaDB-server MariaDB-client galera rsync
因为从10.1开始galera默认依赖,并且包含在mariadb源中,因此安装server和client就可以了。
rsync mariadb默认使用的集群同步工具,centos 7.3 默认已经安装。
2) 安装jemalloc, google 研发的高效内存管理模块,默认系统已安装
yum install jemalloc jemalloc-devel
3)安装Percona XtraBackup
mariadb默认使用rsync进行节点间数据同步.
单rsync同步的时候会锁住节点,没有Percona提供的XtraBackup顺畅.
因此这里使用推荐的XtraBackup,需要下载安装
安装Percona XtraBackup 的yum安装源
yum install -y http://www.percona.com/downloads/percona-release/redhat/0.1-4/percona-release-0.1-4.noarch.rpm
或者手动配置yum源
yum install percona-xtrabackup-24
在yum中查找最新版本进行安装
yum list | grep percona-xtrabackup
yum install -y percona-xtrabackup-24
4)安装socat,否则xtrabackup备份同步方式在单节点故障后重启后在.err错误日志中会报类似以下错误
WSREP_SST: [ERROR] socat not found in path: /usr/sbin:/sbin....
yum install -y socat
5) 配置NTP(chrony)
$ yum install chrony
$ systemctl enable chronyd.service
$ systemctl start chronyd.service
$ systemctl status chronyd.service
6) 启动时,在run里自动创建mysql目录
vi /usr/lib/systemd/system/mariadb.service
[Service]
......
#PermissionsStartOnly=true
RuntimeDirectory=mysql
RuntimeDirectoryMode=0755
User=mysql
Group=mysql
......
修改root用户默认密码
本文中选择IP为192.168.56.21的虚机作为演示节点进行配置,mariadb安装后默认服务是启动的
1) 修改root用户默认密码
mysqladmin -u root password "root的登录密码"
或者
mysql_secure_installation (这种方式初学者可能会选错,所以建议用前一种方式)
2) 本文使用sst_user用户作为集群的数据同步用户,授予所有权限
进入mysql管理命令
mysql -uroot -p
MariaDB> CREATE USER 'sst_user'@'localhost' IDENTIFIED BY 'sst_pass';
MariaDB> GRANT ALL PRIVILEGES ON *.* TO 'sst_user'@'localhost' IDENTIFIED BY 'sst_pass';
# (如果想让用户拥有授有权限,在语句最后加WITH GRANT OPTION)
MariaDB> FLUSH PRIVILEGES;
关闭mysql服务,为后续配置做准备
systemctl stop mariadb
数据目录准备:
1) 安装 semanage 管理工具
yum -y install policycoreutils-python
2) 准备pid socket 目录,防止内存里
mkdir /var/run/mysql
chown -R mysql:mysql /var/run/mysql
mkdir -p /data/{mysql,tmp/mysql,log/mysql}
3) 数据目录权限和selinux上下文
chown -R mysql:mysql /data/mysql
chmod -R 0755 /data/mysql
semanage fcontext -a -t mysqld_db_t "/data/mysql(/.*)?"
restorecon -RFv /data/mysql
4) 临时目录权限和selinux上下文
chown -R mysql:mysql /data/tmp/mysql
chmod -R 0755 /data/tmp/mysql
semanage fcontext -a -t mysqld_db_t "/data/tmp/mysql(/.*)?"
restorecon -RFv /data/tmp/mysql
5) 日志目录权限和selinux上下文
chown -R mysql:mysql /data/log/mysql
chmod -R 0755 /data/log/mysql
semanage fcontext -a -t var_log_t "/data/log/mysql(/.*)?"
restorecon -RFv /data/log/mysql
6) socket selinux设置
semanage fcontext -a -t mysqld_var_run_t "${DB_datadir}/{mysql.sock,mysql.pid}"
restorecon -RFv ${DB_datadir}/{mysql.sock,mysql.pid}
7) 设置 端口 selinux
semanage port -a -t mysqld_port_t -p tcp 3306
修改配置文件
配置文件路径:
/etc/my.cnf.d/server.cnf
mariadb的配置文件很多,安装之后有
/etc/my.cnf
/etc/my.cnf.d/mysql-clients.cnf
/etc/my.cnf.d/server.cnf
其中/etc/my.cnf文件中包含了后两者
/etc/my.cnf.d/mysql-client.cnf中存放客户端连接时的配置信息,
例如[client]和[mysql],/etc/my.cnf.d/server.cnf中存放服务器的配置信息
可以将所有信息添加到server.cnf,也可以分为client和server配置文件
查找配置文件所在位置以及配置信息的命令,按空格键下翻
mysqld –help –verbose | more
1 |
|
启动初始化及注意事项
1) 在其它两个节点上复制配置文件,注意其中的wsrep_node_name和wsrep_node_address需要根据节点实际情况修改
2) 初始化所有节点的数据库
mkdir /var/run/mysql
chown -R mysql:mysql /var/run/mysql
rm -rf /var/lib/mysql/*
rm -rf /data/mysql/*
mysql_install_db --basedir=/usr --datadir=/data/mysql --user=mysql
测试结果,所有节点配置一样,如果第一个节点有数据,运行galera_new_cluster启动cluster,后面的加入的节点数据目录可以为空。
临时关闭安全
setenforce 0
systemctl stop firewalld
1 |
|
3) 使用专有命令启动第一个节点
galera_new_cluster
该命令暗示现在没有已存在的集群,启动的这台服务器是这个集群中的第一个,会产生新的集群UUID.
如果集群已经存在还使用该命令会导致启动的服务器和已存在的集群不在一个集群体系中,因为产生了不一样的集群UUID
3) 在保证第一个节点启动后逐个启动其它节点,不要并行启动,可能会出预料不到的问题,如果第一个节点没启动,其它节点无法正常启动。
systemctl start mariadb
# 查看集群大小
mysql -u root -p -e "SHOW STATUS LIKE 'wsrep_cluster_size'"
mysql -uroot -p -e "CREATE DATABASE IF NOT EXISTS tocloud DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;"
mysql -uroot -p -e "GRANT ALL ON tocloud.* TO test@'%' IDENTIFIED BY 'test.9898';"
如果使用xtrabackup-v2作为同步组件,创建后续在集群同步中拥有同步权限的用户并赋予最基本权限
mysql> GRANT RELOAD, LOCK TABLES, PROCESS, REPLICATION CLIENT ON *.* TO 'sst_user'@'localhost' IDENTIFIED BY 'sst_pass';
mysql> FLUSH PRIVILEGES;
或者
mysql -uroot -p -e "grant all privileges on *.* to 'sst_user'@'%' identified by 'sst_pass';FLUSH PRIVILEGES;"
4) 一定注意集群中最后关闭的服务器应该是下次启动的第一个服务器,因为集群判断这台服务器最后关闭所以具有最完整的数据,所以会设置在这台服务器之前关闭的服务器无法正常手动启动,如果强制启动需要手动将grastate.dat文件中的safe_to_boostrap设置为1后强行启动。
重启集群需要修改,最后一个关闭的服务器配置文件下面这个参数为:
wsrep_cluster_address="gcomm://“
然后重启最后关闭的服务器,再重启其它服务器,最后改回第一台的配置重新启动
最后用此命令查看配置id 集群id 及状态是否一致
mysql -u root -p -e "SHOW STATUS LIKE 'wsrep_cluster%'"
Restarting the cluster
If you shut down all nodes, you effectively terminated the cluster (not the data of course, but the running cluster), hence the right way is to start the all the nodes with gcomm://<node1 address>,<node2 address>,...?pc.wait_prim=no again. On one of the nodes set global wsrep_provider_options="pc.bootstrap=true";.
Bootstrapping a new cluster:
$ mysqld --wsrep-new-cluster
Adding another node to a cluster:
$ mysqld --wsrep_cluster_address=gcomm://192.168.0.1 # DNS names work as well
5) 初始化
# mysql_secure_installation
# 添加超级用户:
grant all on *.* to suroot@'127.0.0.1' identified by 'lion.net' with grant option;
grant all on *.* to suroot@'::1' identified by 'lion.net' with grant option;
grant all on *.* to suroot@'localhost' identified by 'lion.net' with grant option;
# 删除空用户和默认用户:
drop user root@'127.0.0.1';
drop user root@'::1';
drop user root@'localhost';
drop user 'root'@'test-db-vm01';
drop user ''@'test-db-vm01';
drop user ''@localhost;
# 删除测试数据库
drop database test;
MariaDB负载均衡
当MariaDB Galera Cluster集群搭建完成后,通过任意一个节点都可以连接进行数据操作。
当然我们可以借助于haproxy或lvs来实现MySQL数据库集群之间的负载均衡
使用mysql-router代理
最好在每个应用的的服务器上安装mysqlrouter
应用最好使用socket连接mysqlrouter
1 |
|
1 |
|
1 |
|
安装设置haproxy
1) 安装
yum install -y haproxy
2) 设置日志,编辑rsyslog
# 取消下面两项注释,并添加一行:
vi /etc/rsyslog.conf
# Provides UDP syslog reception
$ModLoad imudp
$UDPServerRun 514
# 设置rsyslog系统日志配置
echo 'local2.* /var/log/haproxy.log' > /etc/rsyslog.d/haproxy.conf
3) 编辑配置文件
cp /etc/haproxy/haproxy.cfg /etc/haproxy/haproxy.cfg.bk
1 |
|
4) 配置haproxy的防护墙
firewall-cmd --permanent --add-port=9000/tcp
firewall-cmd --permanent --add-port=3030/tcp
firewall-cmd --reload
5) 客户端访问测试
mysql -u root -p -h 192.168.210.252 -P 3030 -e "select Host, User, Password from mysql.user"
错误排查
1)xtrabackup方式的备份同步在单节点故障后重启会查找配置文件中的这个文件夹,否则会报类似以下错误
.err日志文件错误如下:
rm: cannot remove ‘/var/lib/mysql//innobackup.prepare.log’: No such file or directory
rm: cannot remove ‘/var/lib/mysql//innobackup.move.log’: No such file or directory
WSREP_SST: [INFO] Moving the backup to /var/lib/mysql/ (20170725 11:10:34.925)
WSREP_SST: [INFO] Evaluating innobackupex –no-version-check –move-back –force-non-empty-directories ${DATA} &>${DATA}/innobackup.move.log (20170725 11:10:34.928)
WSREP_SST: [ERROR] Cleanup after exit with status:1 (20170725 11:10:34.937)
2017-07-25 11:10:34 140292539795200 [ERROR] WSREP: Process completed with error: wsrep_sst_xtrabackup-v2 –role ‘joiner’ –address ‘192.168.56.12’ –datadir ‘/var/lib/mysql/’ –parent ‘3212’ ” : 1 (Operation not permitted)
2017-07-25 11:10:34 140292539795200 [ERROR] WSREP: Failed to read uuid:seqno and wsrep_gtid_domain_id from joiner script.
2017-07-25 11:10:34 140292899555456 [ERROR] WSREP: SST failed: 1 (Operation not permitted)
2017-07-25 11:10:34 140292899555456 [ERROR] Aborting
innobackup.move.log 日志文件错误如下:
Error: datadir must be specified
2)脑裂问题:
执行下面命令,通过这个命令来强制恢复出现脑裂的节点。
set global wsrep_provider_options="pc.bootstrap=true";
3)避免脏读
Galera Cluster不是真正意义上的全同步复制,存在延迟。
wsrep_causal_reads=ON;
4) 启动不了mairadb
setenforce 0
mkdir /run/mysql
chown mysql:mysql /run/mysql
systemctl restart mariadb
检查集群是否构建成功
# mysql -e "show status like 'wsrep_%'"
+------------------------------+----------------------------------------------------------+
| Variable_name | Value |
+------------------------------+----------------------------------------------------------+
| wsrep_apply_oooe | 0.000000 |
| wsrep_apply_oool | 0.000000 |
| wsrep_apply_window | 0.000000 |
| wsrep_causal_reads | 0 |
| wsrep_cert_deps_distance | 0.000000 |
| wsrep_cert_index_size | 0 |
| wsrep_cert_interval | 0.000000 |
| wsrep_cluster_conf_id | 5 |
| wsrep_cluster_size | 3 |
| wsrep_cluster_state_uuid | 963cd314-7072-11e6-ac31-16d397a77e7e |
| wsrep_cluster_status | Primary |
| wsrep_commit_oooe | 0.000000 |
| wsrep_commit_oool | 0.000000 |
| wsrep_commit_window | 0.000000 |
| wsrep_connected | ON |
| wsrep_flow_control_paused | 0.000000 |
| wsrep_flow_control_paused_ns | 0 |
| wsrep_flow_control_recv | 0 |
| wsrep_flow_control_sent | 0 |
| wsrep_incoming_addresses | 172.29.32.200:3306,172.29.32.201:3306,172.29.32.202:3306 |
| wsrep_last_committed | 0 |
| wsrep_local_bf_aborts | 0 |
| wsrep_local_cached_downto | 18446744073709551615 |
| wsrep_local_cert_failures | 0 |
| wsrep_local_commits | 0 |
| wsrep_local_index | 0 |
| wsrep_local_recv_queue | 0 |
| wsrep_local_recv_queue_avg | 0.083333 |
| wsrep_local_replays | 0 |
| wsrep_local_send_queue | 0 |
| wsrep_local_send_queue_avg | 0.000000 |
| wsrep_local_state | 4 |
| wsrep_local_state_comment | Synced |
| wsrep_local_state_uuid | 963cd314-7072-11e6-ac31-16d397a77e7e |
| wsrep_protocol_version | 5 |
| wsrep_provider_name | Galera |
| wsrep_provider_vendor | Codership Oy <info@codership.com> |
| wsrep_provider_version | 3.5(rXXXX) |
| wsrep_ready | ON |
| wsrep_received | 12 |
| wsrep_received_bytes | 1360 |
| wsrep_repl_data_bytes | 0 |
| wsrep_repl_keys | 0 |
| wsrep_repl_keys_bytes | 0 |
| wsrep_repl_other_bytes | 0 |
| wsrep_replicated | 0 |
| wsrep_replicated_bytes | 0 |
| wsrep_thread_count | 2 |
+------------------------------+----------------------------------------------------------+
具体参数含义解释:
以下参数能对整个集群的做集群完整性检查、节点状态检查、复制健康状态检查、网络瓶颈检查、冲突或死锁检测等,具体参数如下:
wsrep_cluster_state_uuid
#此参数的值是集群的UUID,每个节点应该一致,可以由此看出节点是否还是集群的一员。
wsrep_cluster_status
#集群节点的状态, 正常应该返回primary,其他状态异常,说明出现”分区”或是”split-brain”状况。
wsrep_cluster_conf_id
#显示集群变更次数,所有节点应该一致, 反之说明有节点与集群断开了。
wsrep_cluster_size
#集群中节点的数量。
wsrep_incoming_addresses
#集群中成员的IP地址和端口。
wsrep_connected
#当前是否连接中,如果该值为Off,且wsrep_ready的值也为Off,则说明该节点没有连接到集群。
wsrep_flow_control_paused
#表示复制停止了多长时间,即表明集群因为Slave延迟而慢的程度,值为0~1,越靠近0越好。值为1表示复制完全停止,可优化wsrep_slave_threads的值来改善。
wsrep_flow_control_sent
wsrep_flow_control_sent
#表示该节点已经停止复制了多少次。
wsrep_last_committed
#最新提交事物的记录。
wsrep_local_commits
#本地SQL提交记录。
wsrep_local_cert_failures
#本地事物提交失败记录。
wsrep_local_bf_aborts
#本地事物回滚的次数。
wsrep_local_send_queue
wsrep_local_recv_queue
#本地发送和接收的队列。
wsrep_local_send_queue_avg
wsrep_local_recv_queue_avg
#表示slave事务队列的平均长度,slave瓶颈的预兆。
wsrep_local_state_comment
#是否在同步中,如果wsrep_connected为On,但wsrep_ready为OFF,则可以从该项查看原因。
wsrep_ready
#插件是否应用中。
wsrep_replicated
#随着复制发出的次数。
wsrep_replicated_bytes
#随着复制发出的字节数。
动态增加节点
关于动态增加节点,只需要在/etc/my.cnf.d/server.conf 修改 wsrep_cluster_address=”gcomm://192.168.1.200″ 地址为cluster其中一个节点即可,
然后通过service mysql start 启动服务,会自动增加到集群节点中
注意点:集群是乐观的并发控制,如果有两个事务同时向集群中不同的节点同一行写入并提交,失败的节点将中止,会造成死锁问题
通过设置单点写入多点读取的方式可以解决此问题。下面链接是其中一种解决方案
http://www.severalnines.com/blog/avoiding-deadlocks-galera-set-haproxy-single-node-writes-and-multi-node-reads
目前存在的一些问题可以参考 https://mariadb.com/kb/en/mariadb/documentation/replication-cluster-multi-master/galera/mariadb-galera-cluster-known-limitations/
wsrep_provider_option
https://severalnines.com/blog/understanding-gcache-galera
1) 查看:
mysql> SHOW VARIABLES LIKE 'wsrep_provider_options'\G
...
base_port=4567;gcache.mem_size = 0; gcache.name = /var/lib/mysql/galera.cache; gcache.size = 128M; gcache.page_size = 128M;
...
2) 相关设置
gcache.name 可单独设置缓存文件到另外一个磁盘,提高IO并发
gcache.size 此参数定义作为‘IST增量同步’的内容源的galera.cache文件的大小。此文件设置的大些以便节点重新加入集群式更有可能采用IST而非SST。(默认128M)
base_port 同步的专用端口
偏移量 auto_increment
当更多的 MariaDB 加入到集群之后,集群中的数据库会自动进行协调,并且自动定义偏移量, 这个比较人性化,自动化,如下描述
MariaDB [tocloud]> show variables like 'auto_increment%';
+--------------------------+-------+
| Variable_name | Value |
+--------------------------+-------+
| auto_increment_increment | 3 |
| auto_increment_offset | 2 |
+--------------------------+-------+
配置haproxy
实现功能:
1)健康检查,down机的mysql自动从业务去除
2)负载均衡,配置专用的mysql读,写集群ip,程序通过该IP处理业务
下面haproxy配置使用自带的mysql检测功能,只能检测mysql是否存活。
如果要检测数据库一致性,需要配置xinetd服务写检测脚本通过option httpchk实现(略)
1)安装haproxy
wget http://haproxy.1wt.eu/download/1.4/src/haproxy-1.4.23.tar.gz
tar xvzfhaproxy-1.4.23.tar.gz
cd haproxy-1.4.23
make TARGET=generic
make install
2)添加mysql用户,在集群任何一台操作即可,会自动同步
添加权限,用于haproxy检测,不需要任何权限,haproxy只检测是否能正常连接关闭mysql
mysql -uroot -p
GRANT USAGE ON test.* to gaojinbo@’10.10.10.1′;
3)建立haproxy配置文件
vi /etc/haproxy.cfg
global
maxconn 40000
#debug
daemon
#quiet
user haproxy
group haproxy
nbproc 1
log 127.0.0.1 local3
spread-checks 2
defaults
timeout server 5m
timeout connect 5m
timeout client 5m
timeout http-request 30s
timeout queue 5m
frontend db_haproxy_status
bind :80
default_backend db_status
frontend db_write
bind 10.10.10.21:3306
default_backend cluster_db_write
frontend db_read
bind 10.10.10.22:3306
default_backend cluster_db_read
backend cluster_db_write
mode tcp
option tcpka
balance roundrobin
option mysql-check user gaojinbo
server mdb1 10.10.10.11:3306 weight 1 check port 3306
server mdb2 10.10.10.12:3306 weight 1 check port 3306
server mdb3 10.10.10.13:3306 weight 1 check port 3306
backend cluster_db_read
mode tcp
option tcpka
balance roundrobin
option mysql-check user gaojinbo
server mdb1 10.10.10.11:3306 weight 1 check port 3306
server mdb2 10.10.10.12:3306 weight 1 check port 3306
server mdb3 10.10.10.13:3306 weight 1 check port 3306
backend db_status
mode http
stats enable
#stats scope
#stats hide-version
stats refresh 5s
stats uri /status
stats realm Haproxy statistics
stats auth gaojinbo:gaojinbo.com
说明:
haproxy配置的5分钟超时,如果需要mysql长连接的话,修改超时设置即可
4)启动haproxy
haproxy -f /etc/haproxy.cfg
总结
通过上面的一系列测试,最后总结一下:
1. 在生产环境下应该避免使用大事务,不建议在高并发写入场景下使用Galera Cluster架构,会导致集群限流,从而引起整个集群hang住,出现生产故障。针对这种情况可以考虑主从,实现读写分离等手段。
2. 对数据一致性要求较高,并且数据写入不频繁,数据库容量也不大(50GB左右),网络状况良好的情况下,可以考虑使用Galera方案
3. MyISAM存储的表,Galera不支持同步。它仅支持XtraDB/ InnoDB存储引擎(虽然有对MyISAM实验支持,具体看wsrep_replicate_myisam系统变量)。
参考:
https://my.oschina.net/ioooi/blog/1476604
http://blog.csdn.net/jiangshouzhuang/article/details/62468778
http://www.cnblogs.com/sweetchildomine/p/7884960.html